package com.shengzhe.ostudent.controller.base;

import com.alibaba.fastjson.JSON;
import com.shengzhe.ostudent.entity.Role;
import com.shengzhe.ostudent.utils.OsBeanUtils;
import com.shengzhe.ostudent.utils.request.RequestLocalHolder;
import lombok.Getter;
import org.apache.commons.io.IOUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;

@Getter
public class BaseController extends HttpServlet {
//    private String pathInfo;
//    private HttpServletRequest request;

    public String getPathInfo() {
        return RequestLocalHolder.getPathInfoByThreadLocal();
    }

    public HttpServletRequest getRequest() {
        return RequestLocalHolder.getHttpServletRequest();
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        this.pathInfo = req.getPathInfo();
//        this.request = req;
        super.service(req, resp);
    }

    //    protected String getPathInfo() {
//        return pathInfo;
//    }
    public <T> T getBodyBean(Class<T> clazz) throws IOException {
        String jsonStr = IOUtils.toString(this.getRequest().getInputStream(), StandardCharsets.UTF_8);
        //System.out.println(jsonStr);
        return JSON.parseObject(jsonStr, clazz);
    }

    /**
     * 请求参数转换为实体类
     *
     * @param beanClass 实体类的class
     * @return 实体类对象
     */
    public <T> T getReqBean(Class<T> beanClass) {    // 声明一个方法，使用泛型接收任何类，并返回与传入类对应的实例化对象
        try {
            // 通过传入的class实例化一个对象，因为这个class通过泛型传入，所以这里返回的是类型也是泛型T
            T bean = beanClass.newInstance();
            /*
            调用OsBeanUtils.getPrivateFields(beanClass)方法，取出传入class包括其父类的所有私有字段
            之后循环遍历所有的私有字段
             */
            for (Field field : OsBeanUtils.getPrivateFields(beanClass)) {
                // 获取这个字段的名字
                String paramName = field.getName();
                /*
                通过这个字段名去请求对象中取查询参数，比如调用方法时传入的类中有id、name、age字段
                那么在这个循环中遍历时，就会从请求中尝试获取这些字段名对应的查询参数
                */
                String paramValue = this.getRequest().getParameter(paramName);
                // 如果从请求中取出的查询参数存在值，进入这个if
                if (paramValue != null && !paramValue.isEmpty()) {
                    // 调用这个方法，表示可以直接改变这个私有字段的值
                    field.setAccessible(true);
                    // 获取这个字段的类型，比如id是Long，name是String
                    Class<?> type = field.getType();

                    /*
                    调用OsBeanUtils.parseValue(type, paramValue)方法，转换请求参数类型为与类字段相同的类型
                    之后把请求参数的值设置到对应的字段中
                    */
                    field.set(bean, OsBeanUtils.parseValue(type, paramValue));
                }
            }
            // 到这一步，已经将请求参数中的值映射到了传入的类实例化出的这个对象中，返回这个对象
            return bean;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
